package com.evolved.automata.experimental;
import java.util.*;

public class StateValueDistribution 
{

	HashMap<Integer, HashMap<Integer, FrequencyCount>> valueDistribution;
	
	int totalCount=0;
	double baseRadius=0.0;
	
	public StateValueDistribution(double radius)
	{
		baseRadius=radius;
		valueDistribution = new HashMap<Integer, HashMap<Integer, FrequencyCount>>();
	}
	
	public void addValue(int newValue)
	{
		HashMap<Integer, FrequencyCount> neighborHood = valueDistribution.get(newValue);
		HashMap<Integer, FrequencyCount> otherNeighborHood;
		
		FrequencyCount priorCount,fCounter = new FrequencyCount(1);
		
		boolean newP=false;
		if (neighborHood==null)
		{
			
			neighborHood = new HashMap<Integer, FrequencyCount>();
			valueDistribution.put(newValue, neighborHood);
			neighborHood.put(newValue, fCounter);
			newP=true;
		}
		else
		{
			fCounter=neighborHood.get(newValue);
			fCounter.incrementCount(1);
		}
		
		if (newP)
		{
			for (Integer otherValues:valueDistribution.keySet().toArray(new Integer[0]))
			{
				otherNeighborHood=valueDistribution.get(otherValues);
				priorCount=otherNeighborHood.get(otherValues);
				if (Math.abs(otherValues.intValue()-newValue)<baseRadius)
				{
					otherNeighborHood.put(newValue, fCounter);
					neighborHood.put(otherValues, priorCount);
				}
			}
		}
		
		totalCount++;
		
	}
	
	// baseValue is known to exist
	public double distanceWeight(int baseValue, int compValue)
	{
		HashMap<Integer, FrequencyCount> neighborHood = valueDistribution.get(compValue);
		
		Integer[] effectiveNeighborhood;
		if (neighborHood==null)
			effectiveNeighborhood=valueDistribution.keySet().toArray(new Integer[0]);
		else
			effectiveNeighborhood=neighborHood.keySet().toArray(new Integer[0]);
		
		double averageCount=0;
		int tCount=0;
		FrequencyCount fCount;
		for (Integer neighbor:effectiveNeighborhood)
		{
			if (Math.abs(neighbor.intValue()-compValue)<baseRadius)
			{
				fCount=valueDistribution.get(neighbor).get(neighbor);
				averageCount=averageCount*tCount/(1+tCount)+fCount.getCount()/(1+tCount);
				tCount++;
			}
			
		}
		FrequencyCount baseCount = valueDistribution.get(baseValue).get(baseValue);
		
		
		int avg = totalCount/valueDistribution.size();
		
		if (averageCount/avg<.3)
			return 0.0;
		else
			return Math.min((baseCount.getCount()*1.0)/totalCount, averageCount/totalCount);
	}
}
